get_page_type() must clean up writable pagetable state
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 14 Nov 2005 18:55:40 +0000 (19:55 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 14 Nov 2005 18:55:40 +0000 (19:55 +0100)
before failing, otherwise functions like set_gdt() can
spuriously fail because a page appears to be writable
despite there being pending changes to mapping of that
page in ptwr state.

This should fix the reported cases of crashes in
vcpu_prepare in xenlinux.

Signed-off-by: Keir Fraser <keir@xensource.com>
xen/arch/x86/mm.c

index 47b0f97d9dd7205565b229689310b137496ddd8c..6c9dfbd6cc3808c12409df6615507966a5b1b8de 100644 (file)
@@ -1461,6 +1461,22 @@ int get_page_type(struct pfn_info *page, unsigned long type)
             {
                 if ( unlikely((x & PGT_type_mask) != (type & PGT_type_mask) ) )
                 {
+                    if ( current->domain == page_get_owner(page) )
+                    {
+                        /*
+                         * This ensures functions like set_gdt() see up-to-date
+                         * type info without needing to clean up writable p.t.
+                         * state on the fast path.
+                         */
+                        LOCK_BIGLOCK(current->domain);
+                        cleanup_writable_pagetable(current->domain);
+                        y = page->u.inuse.type_info;
+                        UNLOCK_BIGLOCK(current->domain);
+                        /* Can we make progress now? */
+                        if ( ((y & PGT_type_mask) == (type & PGT_type_mask)) ||
+                             ((y & PGT_count_mask) == 0) )
+                            goto again;
+                    }
                     if ( ((x & PGT_type_mask) != PGT_l2_page_table) ||
                          ((type & PGT_type_mask) != PGT_l1_page_table) )
                         MEM_LOG("Bad type (saw %" PRtype_info